package com.doubao.wechat.controller;

import com.doubao.common.result.Result;
import com.doubao.wechat.config.WxPayConfig;
import com.doubao.wechat.dto.request.WxPayOrderRequest;
import com.doubao.wechat.dto.response.WxPayOrderResponse;
import com.doubao.wechat.entity.PaymentOrder;
import com.doubao.wechat.listener.PaymentCallbackHandler;
import com.doubao.wechat.mapper.PaymentOrderMapper;
import com.doubao.wechat.service.WxPayService;
import com.doubao.wechat.service.WechatService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付控制器
 */
@RestController
@RequestMapping("/wechat/pay")
@RequiredArgsConstructor
@Tag(name = "微信支付", description = "微信支付相关接口")
@Slf4j
public class WxPayController {

    private final WxPayService wxPayService;
    private final PaymentCallbackHandler paymentCallbackHandler;
    private final PaymentOrderMapper paymentOrderMapper;
    private final WechatService wechatService;


    @PostMapping("/order")
    @Operation(summary = "JSAPI/小程序下单", description = "创建微信支付订单")
    public Result<WxPayOrderResponse> createOrder(@Valid @RequestBody WxPayOrderRequest request) {
        return wxPayService.createOrder(request);
    }

    @GetMapping("/query/{outTradeNo}")
    @Operation(summary = "查询订单", description = "根据商户订单号查询订单")
    public Result<Map<String, Object>> queryOrder(
            @PathVariable("outTradeNo") String outTradeNo,
            @RequestHeader(value = "Authorization", required = false) String authorization,
            @RequestHeader(value = "X-User-ID", required = false) Long userId) {

        log.info("查询订单请求，商户订单号: {}, 用户ID: {}, 认证信息: {}",
                outTradeNo,
                userId,
                authorization != null ? "已提供" : "未提供");

        // 获取微信支付配置
        WxPayConfig wxPayConfig = wxPayService.getWxPayConfig();
        log.info("当前微信支付配置信息: 商户号={}, 证书序列号={}, 私钥路径={}, 域名={}",
                wxPayConfig.getMchId(),
                wxPayConfig.getMchSerialNo(),  // 使用配置中的序列号，而不是硬编码的常量
                wxPayConfig.getPrivateKeyPath(),
                wxPayConfig.getDomain());

        try {
            Result<Map<String, Object>> result = wxPayService.queryOrder(outTradeNo);
            if (result.isSuccess()) {
                log.info("订单查询成功: {}", outTradeNo);
            } else {
                log.error("订单查询失败: {}, 原因: {}", outTradeNo, result.getMessage());
            }
            return result;
        } catch (Exception e) {
            log.error("查询订单发生异常", e);
            return Result.failed("查询订单异常: " + e.getMessage());
        }
    }

    @PostMapping("/close/{outTradeNo}")
    @Operation(summary = "关闭订单", description = "根据商户订单号关闭订单")
    public Result<Boolean> closeOrder(@PathVariable("outTradeNo") String outTradeNo) {
        return wxPayService.closeOrder(outTradeNo);
    }

    @PostMapping("/refund")
    @Operation(summary = "申请退款", description = "申请订单退款")
    public Result<Map<String, Object>> refund(
            @RequestParam("outTradeNo") String outTradeNo,
            @RequestParam("outRefundNo") String outRefundNo,
            @RequestParam("amount") Integer amount,
            @RequestParam(value = "reason", required = false) String reason) {
        return wxPayService.refund(outTradeNo, outRefundNo, amount, reason);
    }

    @PostMapping("/notify")
    public Map<String, Object> payNotify(HttpServletRequest request) {
        try {
            // 读取通知数据
            String notifyData = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
            log.info("【支付通知】接收到微信支付通知：{}", notifyData);

            // 解析通知数据
            log.info("【支付通知】开始解析微信支付通知数据...");
            Result<Map<String, Object>> result = wxPayService.parsePayNotify(notifyData);
            
            if (result.isSuccess()) {
                Map<String, Object> data = result.getData();
                log.info("【支付通知】解析微信支付通知成功，通知数据: {}", data);

                // 提取支付结果信息
                String eventType = (String) data.get("event_type");
                log.info("【支付通知】支付通知事件类型: {}", eventType);

                if ("TRANSACTION.SUCCESS".equals(eventType)) {
                    // 获取商户订单号
                    Map<String, Object> resource = (Map<String, Object>) data.get("resource");
                    log.info("【支付通知】支付成功通知资源数据: {}", resource);
                    
                    if (resource != null) {
                        Map<String, Object> resourceInfo = (Map<String, Object>) resource.get("ciphertext");
                        
                        if (resourceInfo == null) {
                            // 直接使用解密后的数据
                            resourceInfo = (Map<String, Object>) resource.get("decryptData");
                            log.info("【支付通知】使用已解密的通知数据: {}", resourceInfo);
                        } else {
                            log.info("【支付通知】接收到加密的通知数据，需解密");
                        }
                        
                        if (resourceInfo == null) {
                            log.error("【支付通知】无法获取支付通知加密数据");
                            return buildFailResponse("无法获取支付通知加密数据");
                        }
                        
                        // 获取商户订单号和微信支付单号
                        String outTradeNo = (String) resourceInfo.get("out_trade_no");
                        String transactionId = (String) resourceInfo.get("transaction_id");
                        
                        if (outTradeNo == null) {
                            log.error("【支付通知】支付通知中缺少商户订单号");
                            return buildFailResponse("支付通知中缺少商户订单号");
                        }
                        
                        log.info("【支付通知】处理支付成功通知：商户订单号={}, 微信支付单号={}", outTradeNo, transactionId);

                        // 处理支付结果
                        log.info("【支付通知】准备调用支付回调处理器处理支付成功通知");
                        
                        // 记录订单前缀，帮助诊断
                        if (outTradeNo != null && outTradeNo.startsWith("VIP_")) {
                            log.info("【支付通知-会员订单】检测到会员订阅订单支付成功通知: {}", outTradeNo);
                            // 特殊处理会员订单回调，直接调用支付回调处理器
                            try {
                                Result<Void> callbackResult = paymentCallbackHandler.handlePaymentSuccess(outTradeNo, transactionId);
                    if (!callbackResult.isSuccess()) {
                                    log.error("【支付通知-会员订单】会员订单支付回调处理失败: {}, 错误: {}", outTradeNo, callbackResult.getMessage());
                                } else {
                                    log.info("【支付通知-会员订单】会员订单支付回调处理成功: {}", outTradeNo);
                                }
                            } catch (Exception e) {
                                log.error("【支付通知-会员订单】会员订单支付回调处理异常: {}, 错误: {}", outTradeNo, e.getMessage(), e);
                            }
                        }
                        
                        Result<Void> callbackResult = paymentCallbackHandler.handlePaymentSuccess(outTradeNo, transactionId);
                        
                        if (callbackResult.isSuccess()) {
                            log.info("【支付通知】支付回调处理成功，返回成功响应给微信支付");
                            return buildSuccessResponse();
                        } else {
                            log.error("【支付通知】支付回调处理失败: {}", callbackResult.getMessage());
                            // 即使处理失败，也向微信返回成功，避免重复回调
                            log.info("【支付通知】虽然处理失败，但仍返回成功给微信，避免重复通知");
                            return buildSuccessResponse();
                        }
                    } else {
                        log.error("【支付通知】支付通知资源数据为空");
                        return buildFailResponse("支付通知资源数据为空");
                    }
                } else {
                    log.warn("【支付通知】非支付成功通知，忽略处理: eventType={}", eventType);
                    return buildSuccessResponse();
                }
            } else {
                log.error("【支付通知】解析微信支付通知失败: {}", result.getMessage());
                return buildFailResponse("解析微信支付通知失败: " + result.getMessage());
            }
        } catch (Exception e) {
            log.error("【支付通知】处理微信支付通知异常", e);
            return buildFailResponse("处理微信支付通知异常: " + e.getMessage());
        }
    }

    @PostMapping("/refund/notify")
    @Operation(summary = "退款结果通知", description = "接收微信退款结果通知")
    public Map<String, Object> refundNotify(HttpServletRequest request) {
        try {
            // 读取通知数据
            String notifyData = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
            log.info("接收到微信退款通知：{}", notifyData);

            // 处理通知
            // 实现退款回调处理逻辑...

            return Map.of(
                    "code", "SUCCESS",
                    "message", "成功"
            );
        } catch (Exception e) {
            log.error("处理微信退款通知异常", e);
            return Map.of(
                    "code", "FAIL",
                    "message", "系统错误"
            );
        }
    }

    @PostMapping("/create-order")
    @Operation(summary = "创建支付订单", description = "创建微信支付订单")
    public Result<Map<String, Object>> createPaymentOrder(
            @RequestHeader(value = "X-User-ID", required = true) Long userId,
            @RequestParam("productId") Long productId,
            @RequestParam("amount") Integer amount,
            @RequestParam("subject") String subject,
            @RequestParam("body") String body,
            @RequestParam("payChannel") String payChannel,
            @RequestParam("payType") String payType,
            @RequestParam("attach") String attach,
            @RequestParam("clientIp") String clientIp) {
        return wxPayService.createPaymentOrder(userId, productId, amount, subject, body, payChannel, payType, attach, clientIp);
    }
    
    /**
     * 创建支付交易
     * 处理已有订单的支付请求，用于前端支付调用
     */
    @PostMapping("/create")
    @Operation(summary = "创建支付交易", description = "根据订单信息创建支付交易，供前端调用支付")
    public Result<Map<String, Object>> createPayTransaction(@RequestBody Map<String, Object> params,
                                                          @RequestHeader(value = "X-User-ID", required = false) Long headerUserId) {
        try {
            log.info("接收到支付交易请求: {}", params);
            
            // 获取订单信息
            String orderId = (String) params.get("orderId");
            String orderType = (String) params.get("orderType");
            String payMethod = (String) params.get("payMethod");
            String code = (String) params.get("code"); // 获取微信临时授权码
            String clientIp = (String) params.get("clientIp");
    
            if (orderId == null || orderType == null || payMethod == null) {
                return Result.failed("参数不完整，缺少orderId、orderType或payMethod");
            }
            
            // 获取用户ID - 优先从请求体获取
            Long userId = null;
            Object userIdObj = params.get("userId");
            if (userIdObj != null) {
                userId = Long.valueOf(userIdObj.toString());
                log.info("从请求体获取到用户ID: {}", userId);
            }
            
            // 如果请求体中没有，则从请求头获取
            if (userId == null) {
                userId = headerUserId;
                log.info("从请求头获取到用户ID: {}", userId);
            }
            
            if (userId == null) {
                return Result.failed("缺少用户ID信息");
            }
            
            // 如果提供了code，先使用code绑定openid
            if (StringUtils.isNotBlank(code)) {
                try {
                    Result<?> bindResult = wechatService.bindOpenidToUser(userId, code);
                    if (!bindResult.isSuccess()) {
                        log.warn("绑定openid失败: {}", bindResult.getMessage());
                    } else {
                        log.info("成功绑定openid到用户: {}", userId);
                    }
                } catch (Exception e) {
                    log.error("绑定openid异常", e);
                }
            }

            // 查询订单
            PaymentOrder paymentOrder = paymentOrderMapper.selectByOutTradeNo(orderId);
            if (paymentOrder == null) {
                return Result.failed("订单不存在: " + orderId);
            }
            
            // 检查订单状态
            if (!"WAIT_PAY".equals(paymentOrder.getStatus())) {
                return Result.failed("订单状态不允许支付: " + paymentOrder.getStatus());
            }
            
            // 确定交易类型
            String tradeType = "jsapi"; // 默认为jsapi类型
            if ("miniapp".equalsIgnoreCase(paymentOrder.getPayType()) || "MINIAPP".equalsIgnoreCase(String.valueOf(params.get("tradeType")))) {
                tradeType = "miniapp";
                log.info("检测到小程序支付请求，设置tradeType为miniapp");
            }
            
            log.info("创建支付请求，订单号: {}, 交易类型: {}, 用户ID: {}", orderId, tradeType, userId);
            
            // 创建支付请求
            WxPayOrderRequest request = new WxPayOrderRequest();
            request.setUserId(userId);
            request.setOutTradeNo(orderId);
            request.setDescription(paymentOrder.getSubject());
            request.setTotalAmount(paymentOrder.getAmount());
            request.setAttach(paymentOrder.getAttach());
            request.setClientIp(clientIp != null ? clientIp : paymentOrder.getClientIp());
            request.setTradeType(tradeType);
            
            // 调用支付服务
            Result<WxPayOrderResponse> wxPayResult = wxPayService.createOrder(request);
            if (!wxPayResult.isSuccess()) {
                return Result.failed(wxPayResult.getMessage());
            }
            
            // 返回支付参数给前端
            WxPayOrderResponse wxPayResponse = wxPayResult.getData();
            
            // 记录具体支付参数值，方便调试
            log.info("微信支付返回参数详情：timeStamp={}, nonceStr={}, package={}, signType={}, paySign={}, appId={}",
                    wxPayResponse.getTimeStamp(),
                    wxPayResponse.getNonceStr(),
                    wxPayResponse.getPackageValue(),
                    wxPayResponse.getSignType(),
                    wxPayResponse.getPaySign(),
                    wxPayResponse.getAppId());
            
            // 构建微信支付需要的参数
            Map<String, Object> payParams = new HashMap<>();
            payParams.put("timeStamp", wxPayResponse.getTimeStamp());
            payParams.put("nonceStr", wxPayResponse.getNonceStr());
            payParams.put("package", wxPayResponse.getPackageValue());
            payParams.put("signType", wxPayResponse.getSignType());
            payParams.put("paySign", wxPayResponse.getPaySign());
            
            // 如果是小程序支付，还需要设置appId
            if ("miniapp".equalsIgnoreCase(tradeType)) {
                payParams.put("appId", wxPayResponse.getAppId());
            }
            
            log.info("生成支付参数成功: {}", payParams);
            
            // 返回支付结果
            return Result.success(payParams);
        } catch (Exception e) {
            log.error("创建支付交易异常", e);
            return Result.failed("创建支付交易异常: " + e.getMessage());
        }
    }

    @GetMapping("/client-ip")
    @Operation(summary = "获取客户端IP", description = "获取当前请求的客户端IP地址")
    public Result<String> getClientIp(HttpServletRequest request) {
        String ip = getClientIpAddress(request);
        return Result.success(ip);
    }
    
    /**
     * 获取客户端真实IP
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }

        return ip;
    }

    /**
     * 取消支付订单
     */
    @PostMapping("/cancel")
    @Operation(summary = "取消支付", description = "取消未支付的订单")
    public Result<Void> cancelPayment(@RequestBody Map<String, String> requestMap) {
        String orderId = requestMap.get("orderId");

        if (StringUtils.isBlank(orderId)) {
            log.error("取消支付失败: 订单ID为空");
            return Result.failed("订单ID不能为空");
        }

        try {
            log.info("开始取消支付订单: {}", orderId);

            // 查询订单信息
            PaymentOrder order = paymentOrderMapper.selectByOutTradeNo(orderId);
            if (order == null) {
                log.error("取消支付失败: 未找到订单 {}", orderId);
                return Result.failed("未找到订单信息");
            }

            // 检查订单状态，只有待支付的订单才能取消
            if (!"WAIT_PAY".equals(order.getStatus())) {
                log.warn("取消支付失败: 订单状态不是待支付, orderId={}, status={}", orderId, order.getStatus());
                return Result.failed("只能取消待支付的订单");
            }

            // 调用微信支付关闭订单接口
            Result<Boolean> closeResult = wxPayService.closeOrder(orderId);
            if (!closeResult.isSuccess()) {
                log.warn("微信支付关闭订单失败: {}, 错误: {}", orderId, closeResult.getMessage());
                // 即使微信支付关闭失败，我们仍然更新本地订单状态
                log.info("继续更新本地订单状态为已取消");
            }

            // 更新本地订单状态 - 使用专门的取消订单方法
            int result = paymentOrderMapper.cancelOrder(orderId, "用户取消");

            if (result > 0) {
                log.info("取消支付成功: {}", orderId);
                return Result.success();
            } else {
                log.error("取消支付失败: 更新订单状态失败, orderId={}", orderId);
                return Result.failed("更新订单状态失败");
            }
        } catch (Exception e) {
            log.error("取消支付异常: orderId={}, 错误信息={}", orderId, e.getMessage(), e);
            return Result.failed("取消支付异常: " + e.getMessage());
        }
    }

    private Map<String, Object> buildSuccessResponse() {
        return Map.of(
                "code", "SUCCESS",
                "message", "处理成功"
        );
    }

    private Map<String, Object> buildFailResponse(String message) {
        return Map.of(
                "code", "FAIL",
                "message", message
        );
    }
}